﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SafeScript.MetaModel.Statements
{
    public class NotOperator : Operator
    {
        public Operator Operator;

        public override int GetPrecedence()
        {
            return 40;
        }

        public override ITypeDef ComputeType(ITypeDef goal, bool needsRef, ErrorReport report)
        {
            ITypeDef t = this.Operator.ComputeType(BoolType.Self, false, report);
            // Some error?
            if (t == null)
                return null;

            if ( !( t is InstanceType ))
            {
                this.ReportNotAnObject(this.Operator.Node, report);
                return null;
            }

            if (!t.CanBeAssignedTo(BoolType.Self))
            {
                this.ReportIncompatibleTypes(t, BoolType.Self, report);
                return null;
            }

            return new InstanceType() { Type = BoolType.Self };
        }
    }

    public class PlusOperator : Operator
    {
        public Operator Operator;

        public override int GetPrecedence()
        {
            return 40;
        }

        public override ITypeDef ComputeType(ITypeDef goal, bool needsRef, ErrorReport report)
        {
            ITypeDef t = this.Operator.ComputeType(NumericType.Self, false, report);
            // Some error?
            if (t == null)
                return null;

            if (!(t is InstanceType))
            {
                this.ReportNotAnObject(this.Operator.Node, report);
                return null;
            }

            if (!t.CanBeAssignedTo(NumericType.Self))
            {
                this.ReportIncompatibleTypes(t, NumericType.Self, report);
                return null;
            }

            return new InstanceType() { Type = NumericType.Self };
        }
    }

    public class MinusOperator : Operator
    {
        public Operator Operator;

        public override int GetPrecedence()
        {
            return 40;
        }

        public override ITypeDef ComputeType(ITypeDef goal, bool needsRef, ErrorReport report)
        {
            ITypeDef t = this.Operator.ComputeType(NumericType.Self, false, report);
            // Some error?
            if (t == null)
                return null;

            if (!(t is InstanceType))
            {
                this.ReportNotAnObject(this.Operator.Node, report);
                return null;
            }

            if (!t.CanBeAssignedTo(NumericType.Self))
            {
                this.ReportIncompatibleTypes(t, NumericType.Self, report);
                return null;
            }

            return new InstanceType() { Type = NumericType.Self };
        }
    }

    public class InvertOperator : Operator
    {
        public Operator Operator;

        public override int GetPrecedence()
        {
            return 40;
        }

        public override ITypeDef ComputeType(ITypeDef goal, bool needsRef, ErrorReport report)
        {
            ITypeDef t = this.Operator.ComputeType(NumericType.Self, false, report);
            // Some error?
            if (t == null)
                return null;

            if (!(t is InstanceType))
            {
                this.ReportNotAnObject(this.Operator.Node, report);
                return null;
            }

            if (!t.CanBeAssignedTo(NumericType.Self))
            {
                this.ReportIncompatibleTypes(t, NumericType.Self, report);
                return null;
            }

            return new InstanceType() { Type = NumericType.Self };
        }
    }
}
